﻿using Lazy.Captcha.Core;
using RuoYi.Common.Utils;
using RuoYi.Data.Dtos.Account;
using RuoYi.Data.Models;
using RuoYi.Framework.Cache;
using RuoYi.System.Services;

namespace RuoYi.Admin
{
    /// <summary>
    /// 账号服务
    /// </summary>
    [ApiDescriptionSettings("System")]
    [Route("account")]
    [AllowAnonymous]
    public class SysAccountController : ControllerBase
    {
        private readonly ILogger<SysAccountController> _logger;
        private readonly ICaptcha _captcha;
        private readonly ICache _cache;
        private readonly TokenService _tokenService;
        private readonly SysRegisterService _sysRegisterService;

        private readonly SysConfigService _sysConfigService;
        private readonly SysLoginService _sysLoginService;
        private readonly SysPermissionService _sysPermissionService;
        private readonly SysMenuService _sysMenuService;
        private readonly SysLogininforService _sysLogininforService;

        public SysAccountController(ILogger<SysAccountController> logger,
            ICaptcha captcha,
            ICache cache,
            TokenService tokenService,
            SysRegisterService sysRegisterService,
            SysConfigService sysConfigService,
            SysLoginService sysLoginService,
            SysPermissionService sysPermissionService,
            SysMenuService sysMenuService,
            SysLogininforService sysLogininforService)
        {
            _logger = logger;
            _captcha = captcha;
            _cache = cache;
            _tokenService = tokenService;
            _sysRegisterService = sysRegisterService;
            _sysConfigService = sysConfigService;
            _sysLoginService = sysLoginService;
            _sysPermissionService = sysPermissionService;
            _sysMenuService = sysMenuService;
            _sysLogininforService = sysLogininforService;
        }

        /// <summary>
        /// 获取验证码
        /// </summary>
        /// <returns></returns>
        [HttpGet("captchaImage")]
        public async Task<AjaxResult> GetCaptchaImage()
        {
            //验证码操作处理参考: https://github.com/pojianbing/LazyCaptcha
            bool captchaEnabled = await _sysConfigService.GetCaptchaEnabledAsync();
            if (!captchaEnabled)
            {
                return AjaxResult.Success(new { CaptchaEnabled = captchaEnabled });
            }

            string uuid = Guid.NewGuid().ToString();

            // 生成验证码
            var info = _captcha.Generate(uuid);

            return AjaxResult.Success(new
            {
                Uuid = uuid,
                Img = info.Base64
            });
        }

        /// <summary>
        /// 用户名注册
        /// </summary>
        [HttpPost("register")]
        public async Task<AjaxResult> Register([FromBody] RegisterDto user)
        {
            if (!("true".Equals(await _sysConfigService.GetConfigByKeyAsync("sys.account.registerUser"))))
            {
                return AjaxResult.Error("当前系统没有开启注册功能！");
            }
            string msg = await _sysRegisterService.RegisterAsync(user);
            return StringUtils.IsEmpty(msg) ? AjaxResult.Success() : AjaxResult.Error(msg);
        }

        /// <summary>
        /// 手机号注册
        /// </summary>
        [HttpPost("registerByPhoneNumber")]
        public async Task<AjaxResult> RegisterByPhoneNumber([FromBody] RegisterByPhoneNumberDto user)
        {
            if (!("true".Equals(await _sysConfigService.GetConfigByKeyAsync("sys.account.registerUser"))))
            {
                return AjaxResult.Error("当前系统没有开启注册功能！");
            }
            string msg = await _sysRegisterService.RegisterByPhoneNumberDtoAsync(user);
            return StringUtils.IsEmpty(msg) ? AjaxResult.Success() : AjaxResult.Error(msg);
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <returns></returns>
        [HttpPost("login")]
        public async Task<AjaxResult> Login([FromBody] LoginDto loginDto)
        {
            // 生成令牌
            string token = await _sysLoginService.LoginAsync(loginDto.Username, loginDto.Password);
            return AjaxResult.Success(new { token = token });
        }

        /// <summary>
        /// 验证码登录
        /// </summary>
        /// <returns></returns>
        [HttpPost("loginByCode")]
        public async Task<AjaxResult> LoginByCode([FromBody] LoginByCodeDto loginByCodeDto)
        {
            // 生成令牌
            string token = await _sysLoginService.LoginAsync(loginByCodeDto.Username, loginByCodeDto.Password, loginByCodeDto.Code, loginByCodeDto.Uuid);
            return AjaxResult.Success(new { token = token });
        }

        /// <summary>
        /// 退出
        /// </summary>
        [HttpPost("logout")]
        public AjaxResult Logout()
        {
            LoginUser loginUser = _tokenService.GetLoginUser(App.HttpContext.Request);
            if (loginUser != null)
            {
                string userName = loginUser.UserName;
                // 删除用户缓存记录
                _tokenService.DelLoginUser(loginUser.Token);
                // 记录用户退出日志
                _ = Task.Factory.StartNew(async () =>
                {
                    await _sysLogininforService.InsertLogininforAsync(userName, Constants.LOGOUT, "退出成功");
                });
            }
            return AjaxResult.Success("退出成功");
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        [HttpGet("getInfo")]
        public async Task<AjaxResult> GetInfo()
        {
            SysUserDto user = SecurityUtils.GetLoginUser().User;
            // 角色集合
            List<string> roles = await _sysPermissionService.GetRolePermissionAsync(user);
            // 权限集合
            List<string> permissions = _sysPermissionService.GetMenuPermission(user);

            return AjaxResult.Success(new
            {
                user = user,
                roles = roles,
                permissions = permissions
            });
        }

        /// <summary>
        /// 获取路由信息
        /// </summary>
        [HttpGet("getRouters")]
        public AjaxResult GetRouters()
        {
            long userId = SecurityUtils.GetUserId();
            List<SysMenu> menus = _sysMenuService.GetMenuTreeByUserId(userId);
            var treeMenus = _sysMenuService.BuildMenus(menus);
            return AjaxResult.Success(treeMenus);
        }
    }
}